package com.youshang.nio;

import com.google.common.base.Throwables;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author youshang
 * @date 2021/09/20 15:20
 **/
public class NioClient {
    public static void main(String[] args) throws Exception {
        //准备工作
        Selector selector = init();

        while (true) {
            //1.
            //2. 获取selectionKey集合
            //3. 判断每个selectionKey 的事件
                //3.1 触发连接事件的时候
                //3.2 通过selectionKey获取 Socket Channel，调用连接成功方法 finishConnect()
            selector.select();
            Set<SelectionKey> keySet = selector.selectedKeys();
            for (SelectionKey selectionKey : keySet) {
                if (selectionKey.isConnectable()) {
                    SocketChannel client = (SocketChannel) selectionKey.channel();
                    if (client.isConnectionPending()) {
                        client.finishConnect();
                        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
                        writeBuffer.put((LocalDateTime.now() + "连接成功").getBytes());
                        writeBuffer.flip();
                        client.write(writeBuffer);

                        ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());

                        executorService.execute(() -> {
                            try {
                                while (true) {
                                    writeBuffer.clear();
                                    InputStreamReader inputStreamReader = new InputStreamReader(System.in);
                                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                                    String sendMessage = bufferedReader.readLine();

                                    writeBuffer.put(sendMessage.getBytes());
                                    writeBuffer.flip();
                                    client.write(writeBuffer);
                                }
                            } catch (IOException e) {
                                System.out.println(Throwables.getStackTraceAsString(e));
                            }
                        });
                    }
                    client.register(selector,SelectionKey.OP_READ);
                }else if (selectionKey.isReadable()){
                    SocketChannel channel = (SocketChannel)selectionKey.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int read = channel.read(readBuffer);
                    if ( read > 0 ) {
                        readBuffer.flip();
                        String receiveMessage = new String(readBuffer.array(), 0, read);
                        System.out.println(receiveMessage);
                    }
                }
            }
            keySet.clear();
        }
    }

    public static Selector init() throws Exception {
        //1. 获得SocketChannel
        //2. 将当前的socket Channel 设置为非堵塞的
        //3. 将当前的SocketChannel 与 服务器的 SocketChannel 建立连接
        //4. 声明一个Selector (用于注册Channel)
        //5. Channel 注册 selector
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("localhost", 8899));
        Selector selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        return selector;
    }
}
